package com.project.frame.common.utils;

import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期工具类
 * 
 * @author super_dev_001<br />
 * @version 1.0.0 <br />
 *          <table border="1" cellpadding="3" cellspacing="0">
 *          <tr>
 *          <th align="left" colspan="3"><b>修改历史</b></th>
 *          </tr>
 *          <tr>
 *          <td>修改日期</td>
 *          <td>修改人</td>
 *          <td>修改描述</td>
 *          </tr>
 *          <tr>
 *          <td>2018-6-20</td>
 *          <td>super_dev_001</td>
 *          <td>新建</td>
 *          </tr>
 *          </table>
 */
public abstract class DateUtils extends org.apache.commons.lang3.time.DateUtils {

	public static final String DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss";
	public static final String DEFAULT_PATTERN_DATE = "yyyy-MM-dd";
	public static final String DEFAULT_PATTERN_TIME = "HH:mm:ss";

	/**
	 * 字符串日期转为 Date 型，默认格式 yyyy-MM-dd HH:mm:ss
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @param str
	 * @return java.util.Date
	 */
	public static Date parseDate(Object str) throws ParseException {
		if (str == null){
			return null;
		}
		return parseDate(str.toString(), DEFAULT_PATTERN);
	}

	/**
	 * 字符串日期转为 Date 型，格式为 format
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @param str, format
	 * @return java.util.Date
	 */
	public static Date parseDate(String str, String format)
			throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		Date date = null; // 初始化date
		try {
			date = sdf.parse(str); // Mon Jan 14 00:00:00 CST 2013
		} catch (ParseException e) {
			// e.printStackTrace();
		}
		return date;
	}

	/**
	 * 指定日期的星期数值
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @param date
	 * @return int
	 */
	public static int getDayOfWeek(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.DAY_OF_WEEK);
	}

	/**
	 * 指定日期的月份数值
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @param date
	 * @return int
	 */
	public static int getDayOfMonth(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.DAY_OF_MONTH);
	}

	public static Date setTime(final Date date, String time) {
		final Calendar c = Calendar.getInstance();
		c.setLenient(false);
		c.setTime(date);
		String[] ts = StringUtils.split(time, ':');
		if (ts.length > 0)
			c.set(Calendar.HOUR_OF_DAY, Integer.parseInt(ts[0]));
		if (ts.length > 1)
			c.set(Calendar.MINUTE, Integer.parseInt(ts[1]));
		if (ts.length > 2)
			c.set(Calendar.SECOND, Integer.parseInt(ts[2]));
		return c.getTime();
	}

	/**
	 * 当前时间的秒数
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @return long
	 */
	public static long getSecondTime() {
		return System.currentTimeMillis() / 1000;
	}

	/**
	 * long 的值转为 Date
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @param time
	 * @return java.util.Date
	 */
	public static Date parseDateBySecond(String time) {
		return new Date(Long.parseLong(time) * 1000);
	}

	/**
	 * Date=>String,格式为format
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @param date, format
	 * @return java.lang.String
	 */
	public static String format(Date date, String format) {
		if (date == null) {
			return "";
		}
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			return sdf.format(date);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	/**
	 * 之后/之前几天的时间
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @param date, days
	 * @return java.util.Date
	 */
	public static Date afterDays(Date date, int days) {
		if (days == 0) {
			return date;
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DAY_OF_YEAR, days);
		return cal.getTime();
	}


	/**
	 * 判断当前时间是否在时间date2之前
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @param date2
	 * @return boolean
	 */
	public static boolean isDateBefore(Date date2) {
		Date date1 = new Date();// 当前时间
		return date1.before(date2);
	}


	/**
	 * 计算两个日期之间相差的天数
	 * 
	 * @param smdate
	 *            较小的时间
	 * @param bdate
	 *            较大的时间
	 * @return 相差天数
	 * @throws ParseException
	 */
	public static int daysBetween(Date smdate, Date bdate)
			throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		smdate = sdf.parse(sdf.format(smdate));
		bdate = sdf.parse(sdf.format(bdate));
		Calendar cal = Calendar.getInstance();
		cal.setTime(smdate);
		long time1 = cal.getTimeInMillis();
		cal.setTime(bdate);
		long time2 = cal.getTimeInMillis();
		long between_days = (time2 - time1) / (1000 * 3600 * 24);

		return Integer.parseInt(String.valueOf(between_days));
	}

	/**
	 * 计算两个日期之间相差的秒数
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @param smdate, bdate
	 * @return int
	 */
	public static int timeBetween(Date smdate, Date bdate)
			throws ParseException {
		long a = bdate.getTime();
		long b = smdate.getTime();
		int c = (int) ((a - b) / 1000);
		return c;
	}

	/**
	 * 上月最大日期 30或31号
	 * 
	 * @return
	 */
	public static Date lastMonthMaxDate() {
		Calendar calendar = Calendar.getInstance();
		int month = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, month - 1);
		calendar.set(Calendar.DAY_OF_MONTH,calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		Date date = calendar.getTime();
		return date;
	}

	/**
	 * 上月最小日期 1号
	 * 
	 * @return
	 */
	public static Date lastMonthMinDate() {
		Calendar calendar = Calendar.getInstance();
		int month = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, month - 1);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		Date date = calendar.getTime();
		return date;
	}

	/**
	 * 本月最大日期 30或31号
	 * 
	 * @return
	 */
	public static Date monthMaxDate() {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DAY_OF_MONTH,calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		Date date = calendar.getTime();
		return date;
	}

	/**
	 * 本月最小日期 1号
	 * 
	 * @return
	 */
	public static Date monthMinDate() {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DAY_OF_MONTH,calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		Date date = calendar.getTime();
		return date;
	}


	/**
	 * 获得当天0点时间
	 * 
	 * @return
	 */
	public static Date getTimesmorning() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}

	/**
	 * 获得昨天0点时间
	 * 
	 * @return
	 */
	public static Date getYesterdaymorning() {
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(getTimesmorning().getTime() - 3600 * 24 * 1000);
		return cal.getTime();
	}


	/**
	 * 获得当天24点时间
	 * 
	 * @return
	 */
	public static Date getTimesnight() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY,23);
		cal.set(Calendar.MINUTE,59);
		cal.set(Calendar.SECOND,59);
		cal.set(Calendar.MILLISECOND, 999);
		return cal.getTime();
	}

	/**
	 * 获得本周一0点时间
	 * 
	 * @return
	 */
	public static Date getTimesWeekmorning() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY),
				cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		return cal.getTime();
	}

	/**
	 * 获得本周日24点时间
	 * 
	 * @return
	 */
	public static Date getTimesWeeknight() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getTimesWeekmorning());
		cal.add(Calendar.DAY_OF_WEEK, 6);
		cal.set(Calendar.HOUR_OF_DAY,23);
		cal.set(Calendar.MINUTE,59);
		cal.set(Calendar.SECOND,59);
		return cal.getTime();
	}

	/**
	 * 获得本月第一天0点时间
	 * 
	 * @return
	 */
	public static Date getTimesMonthmorning() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
		return cal.getTime();
	}

	/**
	 * 获得本月最后一天24点时间
	 * 
	 * @return
	 */
	public static Date getTimesMonthnight() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
		cal.set(Calendar.DAY_OF_MONTH,cal.getActualMaximum(Calendar.DAY_OF_MONTH));
//		cal.set(Calendar.HOUR_OF_DAY, 24);
		return cal.getTime();
	}

	/**
	 * 上月初0点时间
	 * 
	 * @return
	 */
	public static Date getLastMonthStartMorning() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getTimesMonthmorning());
		cal.add(Calendar.MONTH, -1);
		return cal.getTime();
	}

	/**
	 * 本季度开始点时间
	 * 
	 * @return
	 */
	public static Date getCurrentQuarterStartTime() {
		Calendar c = Calendar.getInstance();
		int currentMonth = c.get(Calendar.MONTH) + 1;
		SimpleDateFormat longSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
		Date now = null;
		try {
			if (currentMonth >= 1 && currentMonth <= 3)
				c.set(Calendar.MONTH, 0);
			else if (currentMonth >= 4 && currentMonth <= 6)
				c.set(Calendar.MONTH, 3);
			else if (currentMonth >= 7 && currentMonth <= 9)
				c.set(Calendar.MONTH, 4);
			else if (currentMonth >= 10 && currentMonth <= 12)
				c.set(Calendar.MONTH, 9);
			c.set(Calendar.DATE, 1);
			now = longSdf.parse(shortSdf.format(c.getTime()) + " 00:00:00");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return now;
	}

	/**
	 * 当前季度的结束时间
	 * 
	 * @return
	 */
	public static Date getCurrentQuarterEndTime() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getCurrentQuarterStartTime());
		cal.add(Calendar.MONTH, 3);
		return cal.getTime();
	}

	/**
	 * 本年开始点时间，即1月1日
	 * 
	 * @return
	 */
	public static Date getCurrentYearStartTime() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), 0,1, 0, 0, 0);
		cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.YEAR));
		return cal.getTime();
	}

	/**
	 * 本年结束点时间，即12月31日
	 * 
	 * @return
	 */
	public static Date getCurrentYearEndTime() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getCurrentYearStartTime());
		cal.add(Calendar.YEAR, 1);
		cal.add(Calendar.DAY_OF_YEAR,-1);
		cal.set(Calendar.HOUR_OF_DAY,23);
		cal.set(Calendar.MINUTE,59);
		cal.set(Calendar.SECOND,59);
		return cal.getTime();
	}

	// 上年开始点时间
	public static Date getLastYearStartTime() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getCurrentYearStartTime());
		cal.add(Calendar.YEAR, -1);
		return cal.getTime();
	}


	/**
	 * 指定日期的星期
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @param date
	 * @return java.lang.String
	 */
	public static String getWeekOfDate(Date date) {
		String[] weekDays = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
		if (w < 0)
			w = 0;
		return weekDays[w];
	}

	/**
	 * 年数差
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @param nowTime, workTime
	 * @return int
	 */
	public static int calculateAge(Date nowTime, Date workTime) {
		int year = 0;
		// 当前时间的年月日
		Calendar cal = Calendar.getInstance();
		cal.setTime(nowTime);
		int nowYear = cal.get(Calendar.YEAR);
		int nowMonth = cal.get(Calendar.MONTH);
		int nowDay = cal.get(Calendar.DAY_OF_MONTH);

		// 开始工作时间的年月日
		cal.setTime(workTime);
		int workYear = cal.get(Calendar.YEAR);
		int workMonth = cal.get(Calendar.MONTH);
		int workDay = cal.get(Calendar.DAY_OF_MONTH);

		// 得到工龄
		year = nowYear - workYear; // 得到年差
		// 若目前月数少于开始工作时间的月数，年差-1
		if (nowMonth < workMonth) {
			year = year - 1;
		} else if (nowMonth == workMonth) {
			// 当月数相等时，判断日数，若当月的日数小于开始工作时间的日数，年差-1
			if (nowDay < workDay) {
				year = year - 1;
			}
		}
		return year;
	}

	/**
	 *
	 * @author super_dev_001
	 * @date 2020/1/19
	 * @param date
	 * @return java.lang.String
	 */
	public static String formationDate(Date date) {
		String dateString = "";
		// 获取系统当前时间
		Date now = new Date();
		try {
			long endTime = now.getTime();
			long currentTime = date.getTime();
			// 计算两个时间点相差的秒数
			long seconds = (endTime - currentTime);
			if (seconds < 10 * 1000) {
				dateString = "刚刚";
			} else if (seconds < 60 * 1000) {
				dateString = seconds / 1000 + "秒前";
			} else if (seconds < 60 * 60 * 1000) {
				dateString = seconds / 1000 / 60 + "分钟前";
			} else if (seconds < 60 * 60 * 24 * 1000) {
				dateString = seconds / 1000 / 60 / 60 + "小时前";
			} else if (seconds < 60 * 60 * 24 * 1000 * 30L) {
				dateString = seconds / 1000 / 60 / 60 / 24 + "天前";
			} else if (date.getYear() == now.getYear()) {// 今年并且大于30天显示具体月日
				dateString = new SimpleDateFormat("MM-dd").format(date.getTime());
			} else if (date.getYear() != now.getYear()) {// 大于今年显示年月日
				dateString = new SimpleDateFormat("yyyy-MM-dd").format(date.getTime());
			} else {
				dateString = new SimpleDateFormat("yyyy-MM-dd").format(date);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return dateString;

	}


	//super_dev_001 2020/5/18

	public static Date nextMonthMinDate() {
		Calendar calendar = Calendar.getInstance();
		int month = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, month + 1);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		Date date = calendar.getTime();
		return date;
	}

	public static Date next2MonthMinDate() {
		Calendar calendar = Calendar.getInstance();
		int month = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, month + 2);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		Date date = calendar.getTime();
		return date;
	}

	public static Date before2MonthMinDate() {
		Calendar calendar = Calendar.getInstance();
		int month = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, month - 1);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		Date date = calendar.getTime();
		return date;
	}

	/**
	 * 3个月后最小日期 1号
	 *
	 * @return
	 */
	public static Date after3MonthMinDate() {
		Calendar calendar = Calendar.getInstance();
		int month = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, month + 3);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		Date date = calendar.getTime();
		return date;
	}

	public static Date lastMonthDay(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_MONTH,calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}


	public static final String parseDateToStr(final String format, final Date date)
	{
		return new SimpleDateFormat(format).format(date);
	}


	/**
	 * 增加 LocalDateTime ==> Date
	 */
	public static Date toDate(LocalDateTime temporalAccessor)
	{
		ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
		return Date.from(zdt.toInstant());
	}

	/**
	 * 增加 LocalDate ==> Date
	 */
	public static Date toDate(LocalDate temporalAccessor)
	{
		LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
		ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
		return Date.from(zdt.toInstant());
	}

}
